﻿using SharpDX.DirectInput;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Media;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using Tank.Draw;
using Tank.Role;

namespace Tank
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
            //激活双缓冲技术
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.DoubleBuffer, true);
        }

        bool isOk = false;//是否画完
        bool isFPS = false;//是否记录完一个轮回
        int fps = 0;//fps累加器
        int wfps = 0;//每秒fps值
        /// <summary>
        /// 画界面
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainForm_Paint(object sender, PaintEventArgs e)
        {
            //Stopwatch sw = new Stopwatch();
            //sw.Start();
            isOk = false;
            Graphics g = e.Graphics;
            g.Clear(Color.White);
            switch (Data.indexState)
            {
                case Data.GameState.StartFrame:
                    DrawStart gdi = new DrawStart(ClientSize.Width, ClientSize.Height);
                    g.DrawImage(gdi.getBitmap(), 0f, 0f);
                    break;
                case Data.GameState.GameFrame:
                    DxDirection();
                    //DrawGame dg = new DrawGame(ClientSize.Width, ClientSize.Height);
                    DrawGame dg = new DrawGame(Data.GridSize * 26, Data.GridSize * 26);
                    g.DrawImage(dg.getBitmap(), 0f, 0f);//, ClientSize.Width, ClientSize.Height
                    break;
                case Data.GameState.GameOver:
                    break;
                case Data.GameState.GameSet:
                    break;
            }
            //sw.Stop();
            //TimeSpan ts2 = sw.Elapsed;
            g.DrawString("FPS:" + wfps.ToString(), new Font("宋体", 9f), Brushes.Red, new PointF(10, 10));
            if (isFPS)
            {
                wfps = fps;
                fps = 0;
                isFPS = false;
                //g.DrawString("FPS:" + (1000 / ts2.TotalMilliseconds).ToString("0"), new Font("宋体", 9f), Brushes.Red, new PointF(10, 10));
            }
            fps++;
            isOk = true;
        }

        /// <summary>
        /// 页面加载
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainForm_Load(object sender, EventArgs e)
        {
            Init.Start();
            Thread t = new Thread(startGame);
            t.IsBackground = true;
            t.Start();
            Thread ta = new Thread(TimeAxis);
            ta.IsBackground = true;
            ta.Start();
            Thread f = new Thread(FPS);
            f.IsBackground = true;
            f.Start();
            PlayMusic.startBackMusic();
            Data.indexFrmIntPtr = Handle;

            var dirInput = new SharpDX.DirectInput.DirectInput();
            var allDevices = dirInput.GetDevices();
            foreach (var item in allDevices)
            {
                if (SharpDX.DirectInput.DeviceType.Keyboard == item.Type)
                {
                    curKeyboard = new SharpDX.DirectInput.Keyboard(dirInput);
                    curKeyboard.Acquire();
                }
            }
        }

        /// <summary>
        /// 不断刷新界面
        /// </summary>
        private void startGame()
        {
            while (true)
            {
                try
                {
                    if (isOk)
                    {
                        this.Invalidate();
                        Thread.Sleep(1000 / 30);
                    }
                    else
                        Thread.Sleep(1);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                    return;
                }
            }
        }

        /// <summary>
        /// 记录fps
        /// </summary>
        private void FPS()
        {
            while (true)
            {
                if (isFPS)
                    Thread.Sleep(1);
                else
                {
                    Thread.Sleep(1000);
                    isFPS = true;
                }
            }
        }

        /// <summary>
        /// 按键
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainForm_KeyDown(object sender, KeyEventArgs e)
        {
            switch (Data.indexState)
            {
                case Data.GameState.StartFrame:
                    switch (e.KeyCode)
                    {
                        case Keys.Up:
                        case Keys.W:
                            Data.indexselectTankState = Data.getLastSelectTankState();
                            PlayMusic.selectMusic();
                            break;
                        case Keys.Down:
                        case Keys.S:
                            Data.indexselectTankState = Data.getNextSelectTankState();
                            PlayMusic.selectMusic();
                            break;
                        case Keys.Enter:
                            Data.indexState = Data.GameState.GameFrame;
                            addPlay(Data.indexselectTankState == Data.selectTankState.TwoPlay);
                            addNPC();
                            PlayMusic.selectMusic();
                            PlayMusic.stopBackMusic();
                            break;
                    }
                    break;
                case Data.GameState.GameFrame:
                    GameKeyDown(e);
                    break;
            }
        }

        /// <summary>
        /// 释放按键
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainForm_KeyUp(object sender, KeyEventArgs e)
        {
            switch (Data.indexState)
            {
                case Data.GameState.GameFrame:
                    GameKeyUp(e);
                    break;

            }
        }

        /// <summary>
        /// 添加玩家
        /// </summary>
        private void addPlay(bool istow = false)
        {
            Player p = new Player(Data.play.one, new Point(9 * Data.GridSize, 24 * Data.GridSize));
            Data.playList.Add(p);
            if (istow)
            {
                Player p2 = new Player(Data.play.two, new Point(15 * Data.GridSize, 24 * Data.GridSize));
                Data.playList.Add(p2);
            }
        }

        Random r = new Random();
        /// <summary>
        /// 添加NPC
        /// </summary>
        private void addNPC()
        {
            NPC n1 = new NPC((Data.NPCType)r.Next(0, 3), new Point(0, 0));
            Data.NPCList.Add(n1);
            NPC n2 = new NPC((Data.NPCType)r.Next(0, 3), new Point((Data.GridSize * 26 - Convert.ToInt32(Data.GridSize * Data.TankEnlarge)) / 2, 0));
            Data.NPCList.Add(n2);
            NPC n3 = new NPC((Data.NPCType)r.Next(0, 3), new Point((Data.GridSize * 26 - Convert.ToInt32(Data.GridSize * Data.TankEnlarge)), 0));
            Data.NPCList.Add(n3);
        }

        /// <summary>
        /// 添加玩家子弹
        /// </summary>
        /// <param name="play"></param>
        private void addPlayBullet(Player play)
        {
            if (!Data.BulletList.Contains(play.indexBullet))
            {
                Point p = new Point();
                switch (play.IndexDirection)
                {
                    case Data.Direction.up:
                        p.X = play.indexPoint.X + Convert.ToInt32(Data.GridSize * Data.TankEnlarge * 3 / 4 / 2);
                        p.Y = play.indexPoint.Y;
                        break;
                    case Data.Direction.down:
                        p.X = play.indexPoint.X + Convert.ToInt32(Data.GridSize * Data.TankEnlarge * 3 / 4 / 2);
                        p.Y = play.indexPoint.Y + Convert.ToInt32(Data.GridSize * Data.TankEnlarge);
                        break;
                    case Data.Direction.left:
                        p.X = play.indexPoint.X;
                        p.Y = play.indexPoint.Y + Convert.ToInt32(Data.GridSize * Data.TankEnlarge * 3 / 4 / 2);
                        break;
                    case Data.Direction.right:
                        p.X = play.indexPoint.X + Convert.ToInt32(Data.GridSize * Data.TankEnlarge);
                        p.Y = play.indexPoint.Y + Convert.ToInt32(Data.GridSize * Data.TankEnlarge * 3 / 4 / 2);
                        break;
                    default:
                        break;
                }
                Bullet b = new Bullet(play.IndexDirection, Data.BulletType.PlayBullet, p);
                for (int i = 0; i < Data.playList.Count; i++)
                {
                    if (play == Data.playList[i])
                        Data.playList[i].indexBullet = b;
                }
                Data.BulletList.Add(b);
                PlayMusic.fireMusic();
            }
        }
        /// <summary>
        /// 游戏画面按键
        /// </summary>
        /// <param name="e"></param>
        private void GameKeyDown(KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                //case Keys.W:
                //    setDirection(Data.play.one, Data.Direction.up);
                //    break;
                //case Keys.S:
                //    setDirection(Data.play.one, Data.Direction.down);
                //    break;
                //case Keys.A:
                //    setDirection(Data.play.one, Data.Direction.left);
                //    break;
                //case Keys.D:
                //    setDirection(Data.play.one, Data.Direction.right);
                //    break;
                //case Keys.J:
                //    Player pl = Data.playList.Where(p => p.IndexPlay == Data.play.one).FirstOrDefault();
                //    if (pl != null)
                //        addPlayBullet(pl);
                //    break;
                ////2号玩家
                //case Keys.Up:
                //    setDirection(Data.play.two, Data.Direction.up);
                //    break;
                //case Keys.Down:
                //    setDirection(Data.play.two, Data.Direction.down);
                //    break;
                //case Keys.Left:
                //    setDirection(Data.play.two, Data.Direction.left);
                //    break;
                //case Keys.Right:
                //    setDirection(Data.play.two, Data.Direction.right);
                //    break;
                //case Keys.K:
                //    Player pl2 = Data.playList.Where(p => p.IndexPlay == Data.play.two).FirstOrDefault();
                //    if (pl2 != null)
                //        addPlayBullet(pl2);
                //    break;
                case Keys.Space:
                    Data.isStop = !Data.isStop;
                    break;
            }
        }

        /// <summary>
        /// 游戏画面释放按键
        /// </summary>
        /// <param name="e"></param>
        private void GameKeyUp(KeyEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.W:
                case Keys.S:
                case Keys.A:
                case Keys.D:
                    setTankStop(Data.play.one, true);
                    break;
                case Keys.Up:
                case Keys.Down:
                case Keys.Left:
                case Keys.Right:
                    setTankStop(Data.play.two, true);
                    break;
            }
        }

        /// <summary>
        /// 设置玩家运动方向
        /// </summary>
        /// <param name="play">玩家</param>
        /// <param name="dir">方向</param>
        private void setDirection(Data.play play, Data.Direction dir)
        {
            for (int i = 0; i < Data.playList.Count(); i++)
            {
                if (Data.playList[i].IndexPlay == play)
                {
                    Data.playList[i].IndexDirection = dir;
                    break;
                }
            }
            setTankStop(play, false);
        }

        /// <summary>
        /// 设置玩家坦克是否停止
        /// </summary>
        /// <param name="play"></param>
        /// <param name="istop"></param>
        private void setTankStop(Data.play play, bool istop)
        {
            for (int i = 0; i < Data.playList.Count(); i++)
            {
                if (Data.playList[i].IndexPlay == play)
                {
                    Data.playList[i].IdnexStop = istop;
                    break;
                }
            }
        }

        /// <summary>
        /// 时间轴
        /// </summary>
        private void TimeAxis()
        {
            while (true)
            {
                if (!Data.isStop)
                {
                    Data.playerMove = true;
                    Data.NPCMove = true;
                    Data.BulletMove = true;
                }
                Thread.Sleep(Data.timeAxis);
            }
        }

        #region dx输入
        private Keyboard curKeyboard;

        /// <summary>
        /// 获取运动方向
        /// </summary>
        private void DxDirection()
        {
            var curKeyboardState = curKeyboard.GetCurrentState();
            var curPressedKeys = curKeyboardState.PressedKeys;
            curPressedKeys.ForEach(pp =>
            {
                switch (pp)
                {
                    case Key.W:
                        setDirection(Data.play.one, Data.Direction.up);
                        break;
                    case Key.S:
                        setDirection(Data.play.one, Data.Direction.down);
                        break;
                    case Key.A:
                        setDirection(Data.play.one, Data.Direction.left);
                        break;
                    case Key.D:
                        setDirection(Data.play.one, Data.Direction.right);
                        break;
                    case Key.J:
                        Player pl = Data.playList.Where(p => p.IndexPlay == Data.play.one).FirstOrDefault();
                        if (pl != null)
                            addPlayBullet(pl);
                        break;
                    //2号玩家
                    case Key.Up:
                        setDirection(Data.play.two, Data.Direction.up);
                        break;
                    case Key.Down:
                        setDirection(Data.play.two, Data.Direction.down);
                        break;
                    case Key.Left:
                        setDirection(Data.play.two, Data.Direction.left);
                        break;
                    case Key.Right:
                        setDirection(Data.play.two, Data.Direction.right);
                        break;
                    case Key.K:
                        Player pl2 = Data.playList.Where(p => p.IndexPlay == Data.play.two).FirstOrDefault();
                        if (pl2 != null)
                            addPlayBullet(pl2);
                        break;
                }
            });
        }
        #endregion
    }
}
